package com.xxx.base.util;


import org.apache.commons.beanutils.BeanUtils;
import org.slf4j.helpers.MessageFormatter;

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 支持格式字符串: "{}", "{0}", "{0.name}"
 * @author hubert
 */
public class Msg {
    /**
     * match string like "{0.name}".
     */
//    private static final Pattern PATTERN_PARAM = Pattern.compile("\\{(([0-9]+).([\\w].+))\\}");
    private static final Pattern PATTERN_PARAM = Pattern.compile("\\{(([0-9]+).([\\w]+))\\}");
    private static final Pattern PATTERN_INDEX = Pattern.compile("\\{([0-9]+)\\}");
    private static final Pattern PATTERN_BRACE = Pattern.compile("\\{\\}");


    public static void main(String[] args) {
        String s = "ss{}ssss";
        Matcher m1 = PATTERN_BRACE.matcher(s);
        Matcher m2 = PATTERN_INDEX.matcher(s);
        Matcher m3 = PATTERN_PARAM.matcher(s);
        if (m1.find()) System.out.println("{} find");
        if (m2.find()) System.out.println("{0} find");
        if (m3.find()) System.out.println("{0.name} find");
    }


    /**
     * format String like "my name: {0.name}" use pArgs.
     * @param pFormat
     *            format String.
     * @param pArgs
     *            arguments
     * @return formatted String.
     */
    public static String format(String pFormat, Object... pArgs) {
        if (Utils.isEmpty(pArgs)) {
            return pFormat;
        }
        // find {}
        Matcher matcher = PATTERN_BRACE.matcher(pFormat);
        if (matcher.find()) return MessageFormatter.arrayFormat(pFormat, pArgs).getMessage();
        // find 类似于: {0}
        Matcher m = PATTERN_INDEX.matcher(pFormat);
        if (m.find()) return MessageFormat.format(pFormat, pArgs);
        // find 类似于: {0.name}
        matcher = PATTERN_PARAM.matcher(pFormat);
        if (!matcher.find()) return pFormat;

        StringBuilder sb = new StringBuilder(pFormat);
        matcher = PATTERN_PARAM.matcher(sb);
        List<Object> args = new ArrayList<>(pArgs.length + 2);
        // "{0.name}" regex resolve:
        // group(1) => {0.name}
        // group(2) => 0
        // group(3) => name
        int count = 0;
        while (matcher.find()) {
            Object indexMappedObject = null;
            try {
                int index = Utils.toInt(matcher.group(2), -1);
                if (index < 0) {
                    continue;
                }
                String propExpression = matcher.group(3);
                indexMappedObject = BeanUtils.getProperty(pArgs[index], propExpression);
            } catch (Exception e) {
                // ignore. set it's mapped value is null.
                System.out.println(e.getMessage());
            }
            args.add(indexMappedObject);
            // change "0.name" to "0".
            sb = new StringBuilder(sb.toString().replaceFirst(matcher.group(1), String.valueOf(count)));
//            sb = sb.replaceFirst(matcher.group(1), String.valueOf(count));
            matcher = PATTERN_PARAM.matcher(sb);
            count++;
        }
        return MessageFormat.format(sb.toString(), args.toArray());
    }

}
